package com.ericsson.enap.modules.backup.service.impl;

import com.ericsson.common.util.*;
import com.ericsson.enap.modules.backup.constant.BackupConstant;
import com.ericsson.enap.modules.backup.mapper.ImsDataBackupMapper;
import com.ericsson.enap.modules.backup.service.ImsDataBackupService;
import com.ericsson.enap.modules.backup.utils.ExecCmd;
import com.ericsson.enap.modules.sys.entity.EnipNetelement;
import com.ericsson.enap.modules.sys.entity.EpcDict;
import com.ericsson.enap.modules.sys.mapper.EpcDictMapper;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @description: Ims 备份功能接口实现类
 * @author: wangjingshi
 * @create: 2021-05-31 16:10
 */
@Service
public class ImsDataBackupServiceImpl implements ImsDataBackupService {

    private Logger log = LoggerUtils.Logger(LogFileName.ImsDataBackupJob);

    @Autowired
    private ImsDataBackupMapper imsDataBackupMapper;
    @Autowired
    private EpcDictMapper epcDictMapper;
    @Value("${collectorIp}")
    private String collectorIp;

    @Override
    public List<EnipNetelement> queryNetelementList(int bizType, String collectorIp) {
        return imsDataBackupMapper.queryNetelementList(bizType,collectorIp);
    }

    @Override
    public void insertBackupTable(String absolutePath, String zipFileName, String netName, Long netId, Long netType,String fileSize,String fileType) {
        imsDataBackupMapper.insertBackupTable(absolutePath,zipFileName,netName,netId,netType,fileType,fileSize);
    }


    private void zipAndDeleteFiles(EnipNetelement enipNetelement,File localFile,String zipFileName,String date,int JobNo,String fileType) {
        String netName = enipNetelement.getName();
        String localFileDir = BackupConstant.localPath + date + "/" + enipNetelement.getType() + "/" +netName + "/";
        String cmd = "zip -r " + localFileDir + zipFileName + " " + zipFileName.substring(0,zipFileName.indexOf("."));
        ExecCmd.executeZipCmd(cmd,netName,new File(localFileDir),JobNo);
        FileUtil.deleteDir(localFile);
        File file = new File(localFileDir + zipFileName);
        String fileSize = FileSizeHelper.getHumanReadableFileSize(file.length());
        imsDataBackupMapper.insertBackupTable(localFileDir,zipFileName,netName,enipNetelement.getId(),enipNetelement.getType(),fileSize,fileType);
    }

    /**
     * 备份Backup文件,适配所有网元
     * @param enipNetelement
     * @param date
     */
    @Override
    public void execBackupFile(EnipNetelement enipNetelement, String date,int JobNo) {
        log.info(JobNo+" "+enipNetelement.getName()+" ==== backupFile start ====");
        Long netType = enipNetelement.getType();
        String localBackupPath = BackupConstant.localPath+date+"/"+netType+"/"+enipNetelement.getName()+"/backup/";
        //SBG(101)的跟CSCF(103)和TAS(102)不一样
        String node_cmd = (netType == 101? "'ll -t /storage/brf/backup'" : "'ll /cluster/brf/backup'");
        String backupCmd = "./node_cmd_run"+JobNo+".pl" +
                           " -ssh_str " + enipNetelement.getUsername() +"@"+ enipNetelement.getIp4() +
                           " -ssh_password " + enipNetelement.getPassword() +
                           " -node_cmd " + node_cmd;
        String subBackupPath = ExecCmd.GetBackupFilesCmd(backupCmd,enipNetelement.getName(),JobNo);
        //本地建立backup以及下面的文件夹
        String localPath = (netType == 101?localBackupPath:localBackupPath + subBackupPath);
        FileUtil.newDirs(localPath);
        String chg_to_root_cmd = (netType == 102? "su root" : "sudo bash");
        //SBG(101)的跟CSCF(103)和TAS(102)不一样
        node_cmd = (netType == 101? "\"scp /storage/brf/backup/" + subBackupPath + " " : "\"scp /cluster/brf/backup/" + subBackupPath + "/* ");
        String downloadCmd = "./node_cmd_run"+JobNo+".pl" +
                             " -ssh_str '" + enipNetelement.getUsername() +"@"+ enipNetelement.getIp4() +
                             "' -ssh_password " + enipNetelement.getPassword() +
                             " -chg_to_root_cmd '" + chg_to_root_cmd + "' -root_password '" + enipNetelement.getRootPwd() +
                             "' -node_cmd " + node_cmd +
                             enipNetelement.getLocalUsername() + "@" + collectorIp + ":" +
                             localPath +"/\" -node_cmd_password "+ enipNetelement.getLocalPassword();
        ExecCmd.executeCmd(downloadCmd,enipNetelement.getName(),JobNo);
        this.zipAndDeleteFiles(enipNetelement,new File(localBackupPath),"backup.zip",date,JobNo,"backup");
        this.cleanOldData("backup",netType,enipNetelement.getName());
        log.info(JobNo+" "+enipNetelement.getName()+" ==== backupFile end ====");
    }

    /**
     * 备份sysLog,适配所有网元
     * @param enipNetelement
     * @param date
     */
    @Override
    public void execSysLog(EnipNetelement enipNetelement, String date,int JobNo) {
        log.info(JobNo+" "+enipNetelement.getName()+" ==== execSysLog start ====");
        Long netType = enipNetelement.getType();
        String localSysLogsPath = BackupConstant.localPath+date+"/"+netType+"/"+enipNetelement.getName()+"/sysLog/";
        String sysLogCmd = "./node_cmd_run"+JobNo+".pl " +
                           "-ssh_str 'ssh " + enipNetelement.getUsername() +"@"+ enipNetelement.getIp4() +
                           "' -ssh_password "+ enipNetelement.getPassword() +
                           " -node_cmd 'll /var/log'";
        List<String> sysLogDirs = ExecCmd.getSysLogCmd(sysLogCmd,enipNetelement.getName(),netType,JobNo);
        String chg_to_root_cmd = (netType == 102? "su root" : "sudo bash");
        for(String sysLogDir:sysLogDirs){
            FileUtil.newDirs(localSysLogsPath+sysLogDir);
            String downLoadCmd = "./node_cmd_run"+JobNo+".pl " +
                                 "-ssh_str 'ssh " + enipNetelement.getUsername() +"@"+ enipNetelement.getIp4() +
                                 "' -ssh_password "+ enipNetelement.getPassword() +
                                 " -chg_to_root_cmd '" + chg_to_root_cmd + "' -root_password '" + enipNetelement.getRootPwd() +
                                 "' -node_cmd \"scp /var/log/"+sysLogDir+"/*  " +
                                 enipNetelement.getLocalUsername() + "@" + collectorIp + ":" +
                                 localSysLogsPath+sysLogDir + "/\" -node_cmd_password " + enipNetelement.getLocalPassword();
            ExecCmd.executeCmd(downLoadCmd,enipNetelement.getName(),JobNo);
        }
        this.zipAndDeleteFiles(enipNetelement,new File(localSysLogsPath),"sysLog.zip",date,JobNo,"sysLog");
        this.cleanOldData("sysLog",netType,enipNetelement.getName());
        log.info(JobNo+" "+enipNetelement.getName()+" ==== execSysLog end ====");
    }

    @Override
    public void execCommonLog(EnipNetelement enipNetelement, String date,String logPath,String logName,int JobNo) {
        Long netType = enipNetelement.getType();
        if(netType!=101){
            log.info(JobNo+" "+enipNetelement.getName()+" ==== execCommonLog start ==== "+logName);
            String localConsoleLogsPath = BackupConstant.localPath+date+"/"+netType+"/"+enipNetelement.getName()+"/"+logName+"/";
            if(JobNo==3){
                localConsoleLogsPath = BackupConstant.localPath+date+"/"+netType+"/"+enipNetelement.getName()+"/"+
                        DateUtils.formatDate(new Date(),"HH")+"/"+logName+"/";
            }
            String chg_to_root_cmd = (netType == 102? "su root" : "sudo bash");
            String targetDir = logPath;
            FileUtil.newDirs(localConsoleLogsPath+targetDir);
            String downLoadCmd = "./node_cmd_run"+JobNo+".pl " +
                    "-ssh_str 'ssh " + enipNetelement.getUsername() +"@"+ enipNetelement.getIp4() +
                    "' -ssh_password "+ enipNetelement.getPassword() +
                    " -chg_to_root_cmd '" + chg_to_root_cmd + "' -root_password '" + enipNetelement.getRootPwd() +
                    "' -node_cmd \"scp " + targetDir + "* "+
                    enipNetelement.getLocalUsername() + "@" + collectorIp + ":" +
                    localConsoleLogsPath + targetDir + "/\" -node_cmd_password " + enipNetelement.getLocalPassword();
            ExecCmd.executeCmd(downLoadCmd,enipNetelement.getUsername(),JobNo);
            this.zipAndDeleteFiles(enipNetelement,new File(localConsoleLogsPath),logName+".zip",date,JobNo,logName);
            this.cleanOldData(logName,netType,enipNetelement.getName());
            log.info(JobNo+" "+enipNetelement.getName()+" ==== execCommonLog end ==== "+logName);
        }
    }

    @Override
    public void execLogDump(EnipNetelement enipNetelement, String date, String logName, int JobNo, String dateTime) {
        Long netType = enipNetelement.getType();
        if(netType!=101){
            log.info(JobNo+" "+enipNetelement.getName()+" ==== execLogDump start ==== "+logName);
            String localConsoleLogsPath = BackupConstant.localPath+date+"/"+netType+"/"+enipNetelement.getName()+"/"+logName+"/";
            String chg_to_root_cmd = (netType == 102? "su root" : "sudo bash");
            String logDumpCmd = "./node_cmd_run"+JobNo+".pl " +
                    "-ssh_str 'ssh " + enipNetelement.getUsername() +"@"+ enipNetelement.getIp4() +
                    "' -ssh_password "+ enipNetelement.getPassword() +
                    " -chg_to_root_cmd '" + chg_to_root_cmd + "' -root_password '" + enipNetelement.getRootPwd() +
                    "' -node_cmd 'll /cluster/storage/no-backup/cdclsv/dumps/ | grep '.tgz$'| grep -v 'incomplete''";
            String logDumpFileName = ExecCmd.getLogDumpCmd(logDumpCmd,enipNetelement.getName(),netType,JobNo,dateTime);
            if(!"".equals(logDumpFileName)){
                String targetDir = "/cluster/storage/no-backup/cdclsv/dumps/";
                FileUtil.newDirs(localConsoleLogsPath);
                String downLoadCmd = "./node_cmd_run"+JobNo+".pl " +
                        "-ssh_str 'ssh " + enipNetelement.getUsername() +"@"+ enipNetelement.getIp4() +
                        "' -ssh_password "+ enipNetelement.getPassword() +
                        " -chg_to_root_cmd '" + chg_to_root_cmd + "' -root_password '" + enipNetelement.getRootPwd() +
                        "' -node_cmd \"scp " + targetDir + logDumpFileName + " " +
                        enipNetelement.getLocalUsername() + "@" + collectorIp + ":" +
                        localConsoleLogsPath + logDumpFileName + "\" -node_cmd_password " + enipNetelement.getLocalPassword();
                ExecCmd.executeCmd(downLoadCmd,enipNetelement.getName(),JobNo);
                File file = new File(localConsoleLogsPath + logDumpFileName);
                String fileSize = FileSizeHelper.getHumanReadableFileSize(file.length());
                System.out.println("fileSize:"+fileSize+"  file:"+file.getAbsolutePath());
                String chmodCmd = "chmod a+r " +localConsoleLogsPath + logDumpFileName;
                ExecCmd.executeCmd(chmodCmd,enipNetelement.getName(),JobNo);
                imsDataBackupMapper.insertBackupTable(localConsoleLogsPath ,logDumpFileName,enipNetelement.getName(),enipNetelement.getId(),enipNetelement.getType(),fileSize,"logdump");
            }
            log.info(JobNo+" "+enipNetelement.getName()+" ==== execLogDump end ==== "+logName);
        }
    }




    @Override
    public void execSafLog(EnipNetelement enipNetelement, String date,int JobNo) {
        log.info(JobNo+" "+enipNetelement.getName()+" ==== execSafLog start ==== ");
        Long netType = enipNetelement.getType();
        List<String> safLogs = new ArrayList<>();
        String logName = "safLog";
        switch (Math.toIntExact(enipNetelement.getType())){
            case 103:
                addCSCF(safLogs);
                break;
            case 102:
                addMTAS(safLogs);
                break;
            case 101:
                logName = "otherLog";
                addSBG(safLogs);
                //因为这里需要匹配*psbcc*BER_PL-*这种特殊的路径,所以需要知道具体的路径都有哪些,并将其加入list（safLogs）中
                String psbccCmd = "./node_cmd_run"+JobNo+".pl " +
                        "-ssh_str 'ssh " + enipNetelement.getUsername() +"@"+ enipNetelement.getIp4() +
                        "' -ssh_password "+ enipNetelement.getPassword() +
                        " -node_cmd 'll /storage/system/log/'";
                List<String> psbccList = ExecCmd.getPsbccCmd(psbccCmd, enipNetelement.getName(), JobNo);
                for (String str:psbccList){
                    safLogs.add("/storage/system/log/"+str+"/log/erlang/*");
                    safLogs.add("/storage/system/log/"+str+"/log/sysMon2/*");
                }
                break;
        }
        String localSafLogsPath = BackupConstant.localPath+date+"/"+netType+"/"+enipNetelement.getName()+"/"+logName+"/";
        String chg_to_root_cmd = (netType == 102? "su root" : "sudo bash");
        for(String safLogDir:safLogs){
            String targetDir = safLogDir.substring(0,safLogDir.lastIndexOf("/"));
            FileUtil.newDirs(localSafLogsPath+targetDir);
            String downLoadCmd = "./node_cmd_run"+JobNo+".pl " +
                    "-ssh_str 'ssh " + enipNetelement.getUsername() +"@"+ enipNetelement.getIp4() +
                    "' -ssh_password "+ enipNetelement.getPassword() +
                    " -chg_to_root_cmd '" + chg_to_root_cmd + "' -root_password '" + enipNetelement.getRootPwd() +
                    "' -node_cmd \"scp " + safLogDir + " "+
                    enipNetelement.getLocalUsername() + "@" + collectorIp + ":" +
                    localSafLogsPath + targetDir + "/\" -node_cmd_password " + enipNetelement.getLocalPassword();
            ExecCmd.executeCmd(downLoadCmd,enipNetelement.getName(),JobNo);
        }
        this.zipAndDeleteFiles(enipNetelement,new File(localSafLogsPath),logName+".zip",date,JobNo,logName);
        this.cleanOldData(logName,netType,enipNetelement.getName());
        log.info(JobNo+" "+enipNetelement.getName()+" ==== execSafLog end ==== ");
    }



    private void addMTAS(List<String> safLogs) {
        safLogs.add("/cluster/storage/no-backup/coremw/var/log/saflog/MTASAppLogs/vdicos/*");
        safLogs.add("/cluster/storage/no-backup/coremw/var/log/saflog/FaultManagementLog/alarm/*");
        safLogs.add("/cluster/storage/no-backup/coremw/var/log/saflog/COM/ComSaLog_*");
        safLogs.add("/cluster/storage/no-backup/coremw/var/log/saflog/saLogSystem_*");
        safLogs.add("/cluster/storage/no-backup/coremw/var/log/saflog/saLogAlarm_*");
    }

    private void addCSCF(List<String> safLogs) {
        safLogs.add("/cluster/storage/no-backup/coremw/var/log/saflog/CSCF_*");
        safLogs.add("/cluster/storage/no-backup/coremw/var/log/saflog/FaultManagementLog/alarm/*");
        safLogs.add("/cluster/storage/no-backup/coremw/var/log/saflog/COM/ComSaLog_*");
        safLogs.add("/cluster/storage/no-backup/coremw/var/log/saflog/saLogSystem_*");
        safLogs.add("/cluster/storage/no-backup/coremw/var/log/saflog/saLogAlarm_*");
    }

    private void addSBG(List<String> safLogs) {
        safLogs.add("/var/filem/nbi_root/AlarmLogs/*");
        safLogs.add("/var/filem/nbi_root/AlertLogs/*");
        safLogs.add("/storage/no-backup/coremw/var/log/saflog/sbgLog/*");
        safLogs.add("/storage/no-backup/coremw/var/log/saflog/sbgLog/sbgFirewallLog/*");
//        safLogs.add("/storage/system/log/*psbcc*BER_PL-*/log/erlang/*");
//        safLogs.add("/storage/system/log/*psbcc*BER_PL-*/log/sysMon2/*");
    }




    @Override
    public void deleteOldDumpsData(String cleanDate) {imsDataBackupMapper.deleteOldDumpsData(cleanDate);}

    @Override
    public void execSshCollectFile(List<EnipNetelement> cgList, String date, int JobNo) {
        for(EnipNetelement cg:cgList){
            //备份config.log
            String cmd = backupConfigLog(date, JobNo, cg);
            //备份history.log
            backupHistoryLog(date, JobNo, cg, cmd);
            //备份last.log
            backupLastLog(date, JobNo, cg, cmd);
        }
    }

    //备份last.log
    private void backupLastLog(String date, int JobNo, EnipNetelement cg, String cmd) {
        String lastPath = BackupConstant.localPath+date+"/"+cg.getType()+"/"+cg.getName()+"/last/";
        String last_cmd = cmd + "'sudo last'";
        List<String> lastList = ExecCmd.executeCgCmd(last_cmd, JobNo);
        this.writeNewFile("last.log",lastList,lastPath);
        this.zipAndDeleteFiles(cg,new File(lastPath),"last.zip",date,JobNo,"last");
        this.cleanOldData("last",cg.getType(),cg.getName());
    }

    //备份history.log
    private void backupHistoryLog(String date, int JobNo, EnipNetelement cg, String cmd) {
        String historyPath = BackupConstant.localPath+date+"/"+cg.getType()+"/"+cg.getName()+"/history/";
        String history_cmd = cmd + "'history'";
        List<String> historyList = ExecCmd.executeCgCmd(history_cmd, JobNo);
        this.writeNewFile("history.log",historyList,historyPath);
        this.zipAndDeleteFiles(cg,new File(historyPath),"history.zip",date,JobNo,"history");
        this.cleanOldData("history",cg.getType(),cg.getName());
    }

    //备份config.log
    private String backupConfigLog(String date, int JobNo, EnipNetelement cg) {
        String configPath = BackupConstant.localPath+ date +"/"+ cg.getType()+"/"+ cg.getName()+"/config/";
        String cmd = "./node_cmd_run"+ JobNo +".pl" +
                " -ssh_str " + cg.getUsername() +"@"+ cg.getIp4() +
                " -ssh_password " + cg.getPassword() +
                " -node_cmd ";
        String config_cmd = cmd + "'cat /etc/mediation/MM.config'";
        List<String> configList = ExecCmd.executeCgCmd(config_cmd, JobNo);
        this.writeNewFile("config.log",configList,configPath);
        this.zipAndDeleteFiles(cg,new File(configPath),"config.zip", date, JobNo,"config");
        this.cleanOldData("config", cg.getType(), cg.getName());
        return cmd;
    }

    //清除过期数据
    private void cleanOldData(String logName,Long netType,String netName) {
        String cleanDays = epcDictMapper.selectEpcDict(new EpcDict(logName)).getKeyValue();
        String cleanDate = DateUtils.beforNumDay(new Date(),-Integer.parseInt(cleanDays));
        String cleanDir = BackupConstant.localPath + cleanDate + "/" +
                netType + "/" + netName + "/" + logName + ".zip";
        File cleanFile = new File(cleanDir);
        FileUtil.deleteDir(cleanFile);
        imsDataBackupMapper.deleteOldDataByFileType(cleanDate, logName);
    }

    public void writeNewFile(String fileName, List<String> list, String path) {
        File file = new File(path+fileName);
        if(!file.getParentFile().exists()){
            file.getParentFile().mkdirs();
        }
        try {
            if (!file.exists()) {
                file.createNewFile();
            }
            FileWriter fw = new FileWriter(file.getAbsoluteFile());
            BufferedWriter bw = new BufferedWriter(fw);
            for (int i = 0; i < list.size(); i++) {
                bw.write(list.get(i)+"\r\n");
            }
            fw.flush();
            bw.flush();
            bw.close();
        } catch (IOException e) {
            e.printStackTrace();
            log.error(" ======= writeNewFile ======= ",e.getMessage());
        } finally {

        }
    }




}
